#include "List.h"
#include <iostream> 
using namespace std;

List::List(void) : _head(0), _tail(0), _size(0)
{
}


List::~List(void)
{
}


ListNode* List::add(ExtentIO* eio)
{
	if (_size == 0)
	{
		_head = _tail = new ListNode(eio);
		_head->_next = _tail->_next = 0;
		_head->_prev = _tail->_prev = 0;
	}
	else 
	{
		_tail->_next = new ListNode(eio);
		_tail->_next->_prev = _tail;
		_tail = _tail->_next;
		_tail->_next = 0;
	}
	if (_size == 1)
		_head->_next = _tail;
	_size++;
	return _tail;
}
ExtentIO* List::remove(ListNode* node)
{
	if (_size == 0)
	{
		std::cout << "\nFashla with remove from list - empty list!!!\n";
		throw "\nFashla with remove from list - empty list!!!\n";
	}
	if (_size == 1)
	{
		_head = _tail = 0;
	}
	else if (node == _head)
	{
		_head = _head->_next;
		_head->_prev = 0;
	}
	else if (node == _tail)
	{
		_tail = _tail->_prev;
		_tail->_next = 0;
	}
	else
	{
		node->_prev->_next = node->_next;
		node->_next->_prev = node->_prev;
	}
	_size--;
	ExtentIO* ans = node->_data;
	delete node;
	return ans;
}
void List::moveToIndex(ListNode* node, int index)
{
	if (index >= _size - 1)
		return moveToEnd(node);
	if (node == _head)
	{
		_head = node->_next;
		_head->_prev = NULL;
	}
	else
	{
		node->_prev->_next = node->_next;
		node->_next->_prev = node->_prev;
	}
	// get the place of the node
	ListNode* indexNode = get(index);
	// insert node in place
	indexNode->_prev->_next = node;
	node->_prev = indexNode->_prev;
	indexNode->_prev = node;
	node->_next = indexNode;
		
}
void List::moveToEnd(ListNode* node)
{
	if (_size <= 1)
		return;
	if (node == _head)
	{
		_head = _head->_next;
		_head->_prev = 0;
	}
	else if (node == _tail)
	{
		return;
	}
	else
	{
		node->_prev->_next = node->_next;
		node->_next->_prev = node->_prev;
	}
	node->_prev = _tail;
	node->_next = 0;
	_tail->_next = node;
	_tail = node;

}

void List::print(ListNode* node) const
{
	if (node != NULL)
	{
		cout << node->_data->getLunID() << "->";
		print (node->_next);
	}

}

void List::printList() const
{
	cout << "********************\n";
	cout << "Start printing list\n";

	print(_head);

	cout << "\nFinish printing list\n";
	cout << "********************\n";
}

ListNode* List::getHead() const
{
	return _head;
}
int List::getSize() const 
{
	return _size; 
}

ExtentIO* List::removeHead()
{
	return remove(_head);
}



ListNode* List::get(int index)
{
	// for efficiency we've check if we should start from head or tail.
	if (index < _size / 2)
	{
		ListNode* p = _head;
		for (int i = 0 ; i < index; i++)
			p = p->_next;
		return p;
	}
	else
	{
		ListNode* p = _tail;
		for (int i = 0 ; i < _size - index; i++)
			p = p->_prev;
		return p;
	}
}

void List::clear()
{
	while(_head)
	{
		ListNode* tmp = _head->_next;
		delete _head->getData();
		delete _head;
		_head = tmp;
	}
	_head = _tail = 0;
	_size = 0;
}